#include "sys.h"

uint8_t UsNumber = 0;
RCC_ClocksTypeDef clocks;

void Delay_us(uint32_t nus)
{
    uint32_t ticks, told, tnow, tcnt, reload;
    told = SysTick->VAL;    // 记录进入函数时的值
    reload = SysTick->LOAD; // 记录重载值
    ticks = UsNumber * nus; // 计算sysTick数
    tcnt = 0;               // 记录执行期间计数
    while (1)
    {
        tnow = SysTick->VAL; // 当前值
        if (tnow != told)    // 不断累加流逝的sysTick数
        {
            if (tnow < told)
            {
                tcnt += (told - tnow);
            }
            else
            {
                tcnt += ((reload - tnow) + told);
            }
            told = tnow;
            if (tcnt >= ticks)
            {
                break;
            }
        }
    }
}

uint8_t Delay_us_with_Break_by_Function(uint32_t nus, uint8_t(fun(void)))
{
    uint32_t ticks, told, tnow, tcnt, reload;
    told = SysTick->VAL;
    reload = SysTick->LOAD;
    ticks = UsNumber * nus - 37;
    tcnt = 0;
    while (1)
    {
        tnow = SysTick->VAL;
        if (tnow != told)
        {
            if (tnow < told)
            {
                tcnt += (told - tnow);
            }
            else
            {
                tcnt += ((reload - tnow) + told);
            }
            told = tnow;
            if (tcnt >= ticks)
            {
                return 0;
            }
            if (fun())
            {
                return 1;
            }
        }
    }
}

uint8_t Delay_us_With_Break_by_Value(uint32_t nus, volatile uint8_t *pValue)
{
    uint32_t ticks, told, tnow, tcnt, reload;
    told = SysTick->VAL;
    reload = SysTick->LOAD;
    ticks = UsNumber * nus - 37;
    tcnt = 0;
    while (1)
    {
        tnow = SysTick->VAL;
        if (tnow != told)
        {
            if (tnow < told)
            {
                tcnt += (told - tnow);
            }
            else
            {
                tcnt += ((reload - tnow) + told);
            }
            told = tnow;
            if (tcnt >= ticks)
            {
                return 0;
            }
            if (*pValue)
            {
                return 1;
            }
        }
    }
}

uint16_t CRC16_CCITT_FALSE(uint8_t *puchMsg, uint16_t usDataLen)
{
    uint16_t wCRCin = 0xFFFF;
    uint16_t wCPoly = 0x1021;
    uint8_t wChar = 0;
    while (usDataLen--)
    {
        wChar = *(puchMsg++);
        wCRCin ^= (wChar << 8);
        for (int i = 0; i < 8; i++)
        {
            if (wCRCin & 0x8000)

            {
                wCRCin = (wCRCin << 1) ^ wCPoly;
            }
            else
            {
                wCRCin = wCRCin << 1;
            }
        }
    }
    return (wCRCin);
}

void gpio_init(IOList *pGPIO_Init_Param)
{
    uint8_t i;

    // 初始化IO口
    for (i = 0; i < 64; i++)
    {
        // 退出循环条件
        if ((pGPIO_Init_Param + i)->GPIOx == 0)
        {
            break;
        }

        // 根据需要打开时钟
        switch ((uint32_t)(pGPIO_Init_Param + i)->GPIOx)
        {
        case (uint32_t)GPIOA:
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
            break;
        case (uint32_t)GPIOB:
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
            break;
        case (uint32_t)GPIOC:
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
            break;
        case (uint32_t)GPIOD:
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
            break;
        }
        // 初始化IO口模式
        GPIO_Init((pGPIO_Init_Param + i)->GPIOx, &(pGPIO_Init_Param + i)->GPIO_Param);

        // 设置GPIO PIN电平
        if ((pGPIO_Init_Param + i)->InitValue == 1)
        {
            GPIO_SetBits((pGPIO_Init_Param + i)->GPIOx, (pGPIO_Init_Param + i)->GPIO_Param.GPIO_Pin);
        }
        else
        {
            GPIO_ResetBits((pGPIO_Init_Param + i)->GPIOx, (pGPIO_Init_Param + i)->GPIO_Param.GPIO_Pin);
        }
    }
}

void RCC_ClkConfiguration(void)
{
    RCC_DeInit();                                       // 复位RCC寄存器
    RCC_HSEConfig(RCC_HSE_ON);                          // 使能HSE
    while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET) // 等待HSE就绪
    {
    }
    RCC_PLLCmd(DISABLE);                                                   // 关闭PLL
    AIR_RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_27, FLASH_Div_2); // 配置PLL,8*27=216MHz 取16到23
    RCC_PLLCmd(ENABLE);                                                    // 使能PLL
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)                    // 等待PLL就绪
    {
    }
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);          // 选择PLL作为系统时钟
    RCC_HCLKConfig(RCC_SYSCLK_Div1);                    // 配置AHB时钟
    RCC_PCLK1Config(RCC_HCLK_Div2);                     // 配置APB1时钟
    RCC_PCLK2Config(RCC_HCLK_Div1);                     // 配置APB2时钟
    RCC_LSICmd(ENABLE);                                 // 使能内部低速时钟
    while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) // 等待LSI就绪
    {
    }
    RCC_HSICmd(ENABLE);                                 // 使能内部高速时钟
    while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET) // 等待HSI就绪
    {
    }
    RCC_GetClocksFreq(&clocks);                     // 获取系统时钟频率
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); // 3位抢占优先级，0位子优先级，AIR32只有三位
}

void _putchar(char character)
{
    while ((USART1->SR & USART_FLAG_TC) == 0)
    {
    }
    USART1->DR = character;
}

void Delay_Init()
{
    RCC_GetClocksFreq(&clocks);                           // 获取时钟频率216MHz
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); // SysTick频率27MHz
    UsNumber = clocks.HCLK_Frequency / HSE_VALUE;         // 216MHz / 8MHz = 27次
    SysTick->LOAD = (u16)UsNumber * 1000;                 // Systick初始化为1ms倒计时
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;             // 开启sysTick
}

void print_system_info()
{
    printf("SYSCLK: %3.1fMhz\nHCLK(AHB): %3.1fMhz\nPCLK1(APB1): %3.1fMhz\nPCLK2(APB2): %3.1fMhz, \nADCCLK: %3.1fMhz\n",
           (float)clocks.SYSCLK_Frequency / 1000000, (float)clocks.HCLK_Frequency / 1000000,
           (float)clocks.PCLK1_Frequency / 1000000, (float)clocks.PCLK2_Frequency / 1000000,
           (float)clocks.ADCCLK_Frequency / 1000000);
    Delay_ms(100);
}

// 按PCB上写的8421，
// 如果要返回值为1，短接1
// 如果要返回值为3，短接12
uint8_t read_extra_jump_states()
{
    const IOList extra_gpio[] = {
        {GPIOC, {GPIO_Pin_13, GPIO_Speed_50MHz, GPIO_Mode_IPU}, 1},
        {GPIOB, {GPIO_Pin_4, GPIO_Speed_50MHz, GPIO_Mode_IPU}, 1},
        {GPIOB, {GPIO_Pin_3, GPIO_Speed_50MHz, GPIO_Mode_IPU}, 1},
        {GPIOA, {GPIO_Pin_15, GPIO_Speed_50MHz, GPIO_Mode_IPU}, 1},
        {0, {0, 0, 0}, 0}};
    uint8_t ret = 0xFF;
    gpio_init((IOList *)extra_gpio);
    if (PCin(13) == 0)
    {
        ret &= 0xFE;
    }
    if (PBin(4) == 0)
    {
        ret &= 0xFD;
    }
    if (PBin(3) == 0)
    {
        ret &= 0xFB;
    }
    if (PAin(15) == 0)
    {
        ret &= 0xF7;
    }
    return ~ret;
}

// GPIO13 DI 高位 GPIO14 CLK 低位
// 默认值是 11 即 = 3
uint8_t read_swd_jump_states()
{
    const IOList swd_gpio[] = {
        {GPIOA, {GPIO_Pin_13, GPIO_Speed_50MHz, GPIO_Mode_IPU}, 1},
        {GPIOA, {GPIO_Pin_14, GPIO_Speed_50MHz, GPIO_Mode_IPU}, 1},
        {0, {0, 0, 0}, 0}};
    uint8_t ret = 0x03;
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
    gpio_init((IOList *)swd_gpio);
    if (PAin(14) == 0)
    {
        ret &= 0x02;
    }
    if (PAin(13) == 0)
    {
        ret &= 0x01;
    }
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE);
    return ret;
}